import csv
import io
import chardet
from flask import Blueprint, jsonify, request
from flask_jwt_extended import jwt_required
from libs.conn import *
from libs.utils import *

alarm_notices_bp = Blueprint('alarm_notices', __name__)

# 本机作为中继服务器时接收告警信息。内网服务器会主动将告警信息发送给中继服务器（中继服务器作用：统一配置短信、邮箱、钉钉等接口；很多时候本应用部署在内网，无法直接发送告警信息到外网，可以将中继服务器部署在接近外网的位置，并可以多次中继）
@alarm_notices_bp.route('/api/alarm_notice', methods=['POST'])
def alarm_notice():
    app_id = request.json.get('app_id') # app唯一标识
    check_code = request.json.get('check_code') # 校验是否是从合法的app发送的请求
    notice_type = request.json.get('notice_type') # 通知类型数组，有['email', 'sms', 'dingtalk', 'wechat']
    notice_title = request.json.get('notice_title') # 通知标题
    notice_content = request.json.get('notice_content') # 报警通知内容
    notice_target = request.json.get('notice_target') # 通知目标，如邮箱、手机号、钉钉机器人等
    relay_ttl = int(request.json.get('relay_ttl')) # 中继ttl，当为0时则不再中继
    # 将告警通知信息插入到数据库中
    if app_id == get_config('app_id'):
        return { 'status': 'error', 'data': '不允许向自己发送告警通知' }
    the_app = fetchone("SELECT * FROM apps WHERE app_id = ? and app_checked = 1", (app_id,))
    if the_app is None:
        return { 'status': 'error', 'data': 'app不存在' }
    if the_app['app_checked'] != 1:
        return { 'status': 'error', 'data': 'app未通过审核' }
    if check_code != hash_message(notice_content, the_app['app_secret']):
        return { 'status': 'error', 'data': '校验码错误' }
    if the_app['app_enable'] != 1:
        return { 'status': 'error', 'data': '暂不接收该app通知，请联系管理员' }
    if is_string_valid(notice_type):
        if notice_type not in ['email', 'sms', 'dingtalk', 'wechat']:
            return { 'status': 'error', 'data': '通知类型错误' }
    else:
        return { 'status': 'error', 'data': '通知类型不能为空' }
    
    notice_force_relay = get_config('notice_force_relay') == '1'
    notice_ok, message = send_notice(notice_type, notice_target, notice_title, notice_content, notice_force_relay, relay_ttl) # 发送通知
    if notice_ok:
        notice_id = execute("INSERT INTO alarm_notices (app_id, app_name, notice_type, notice_time, notice_content, notice_source, notice_target, notice_sent) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", (app_id, the_app['app_name'], notice_type, get_time(), notice_content, 'app', notice_target, 1))
        execute("INSERT INTO system_logs (log_content, log_time) VALUES (?, ?)", (f'发送{notice_type}通知【{notice_title}】成功，notice_id: {str(notice_id)}', get_time()))
        return { 'status': 'ok', 'data': 'success' }
    else:
        notice_id = execute("INSERT INTO alarm_notices (app_id, app_name, notice_type, notice_time, notice_content, notice_source, notice_target, notice_sent) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", (app_id, the_app['app_name'], notice_type, get_time(), notice_content, 'app', notice_target, 2))
        execute("INSERT INTO system_logs (log_content, log_time) VALUES (?, ?)", (f'发送{notice_type}通知【{notice_title}】失败，notice_id: {str(notice_id)}，失败原因: {message}', get_time()))
        return { 'status': 'error', 'data': message }

@alarm_notices_bp.route('/api/get_alarm_notices', methods=['GET'])
@jwt_required()
def get_alarm_notices():
    app_id = request.args.get('app_id')
    notice_type = request.args.get('notice_type')
    notice_content = request.args.get('notice_content')
    page_size = int(request.args.get('page_size'))
    page_current = int(request.args.get('page_current'))
    sql = "FROM alarm_notices WHERE 1=1"
    params = []
    if is_string_valid(app_id):
        sql += " AND app_id = ?"
        params.append(app_id)
    if is_string_valid(notice_type):
        sql += " AND notice_type = ?"
        params.append(notice_type)
    if is_string_valid(notice_content):
        sql += " AND notice_content LIKE ?"
        params.append('%' + notice_content + '%')
    offset = (page_current - 1) * page_size
    rows = fetchall("SELECT * " + sql + " ORDER BY notice_id DESC LIMIT ?, ?", tuple(params + [offset, page_size]))
    total_count = fetchvalue("SELECT COUNT(*) " + sql, tuple(params))
    return { 'status': 'ok', 'data': rows, 'page_total': total_count }
